package com.yuyou.fn.updater.handler;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Optional;
import com.google.common.cache.LoadingCache;
import com.yuyou.fn.common.database.event.EventHandler;
import com.yuyou.fn.common.database.event.IEventHandler;
import com.yuyou.fn.common.util.BigDecimals;
import com.yuyou.fn.common.util.CacheUtils;
import com.yuyou.fn.common.util.Threads;
import com.yuyou.fn.common.util.Utils;
import com.yuyou.fn.educational.entity.ClassLecture;
import com.yuyou.fn.educational.entity.CourseClass;
import com.yuyou.fn.educational.entity.CourseTemplate;
import com.yuyou.fn.educational.entity.Student;
import com.yuyou.fn.educational.service.IClassLectureService;
import com.yuyou.fn.educational.service.ICourseClassService;
import com.yuyou.fn.educational.service.ICourseTemplateService;
import com.yuyou.fn.educational.service.IStudentService;
import com.yuyou.fn.report.entity.ConsumeRecord;
import com.yuyou.fn.report.service.IConsumeRecordService;
import com.yuyou.fn.settlement.constant.IncomeCategoryEnum;
import com.yuyou.fn.settlement.constant.Subjects;
import com.yuyou.fn.settlement.entity.ChangeRecord;
import com.yuyou.fn.settlement.service.ITradePropService;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;

@EventHandler(tables = {"yyfn.change_record"})
@Component
public class ConsumeRecordUpdater implements IEventHandler {

    private final static Logger log = LoggerFactory.getLogger(ConsumeRecordUpdater.class);


    @Resource
    private ITradePropService tradePropService;

    @Resource
    private IStudentService studentService;

    @Resource
    private ICourseClassService courseClassService;

    @Resource
    private ICourseTemplateService courseTemplateService;

    @Resource
    private IConsumeRecordService consumeRecordService;

    @Resource
    private IClassLectureService classLectureService;


    private LoadingCache<Long,Optional<CourseTemplate>> loadingCacheOfCourseTemplate ;
    private LoadingCache<Long,Optional<CourseClass>> loadingCacheOfCourseClass ;
    private LoadingCache<Long,Optional<Student>> loadingCacheOfStudent ;
    private LoadingCache<Long,Optional<Map<String, String>>> loadingCacheOfTradeProp ;

    @PostConstruct
    public void init(){
        this.loadingCacheOfCourseTemplate = CacheUtils.buildCache(courseTemplateService::findById);
        this.loadingCacheOfCourseClass = CacheUtils.buildCache(courseClassService::findById);
        this.loadingCacheOfStudent = CacheUtils.buildCache(studentService::findById);
        this.loadingCacheOfTradeProp = CacheUtils.buildCache(tradePropService::findByTradeId);
    }

    @Override
    public void insert(String tableName, JSONArray rowList) {

        build(tableName, rowList);
    }

    @Override
    public void update(String tableName, JSONArray rowList, Set<String> updateColumns) {
        build(tableName, rowList);

    }

    @Override
    public void delete(String tableName, JSONArray rowList) {

    }

    private void build(String tableName, JSONArray rowList) {
        for (int i = 0; i < rowList.size(); i++) {
            JSONObject row = rowList.getJSONObject(i);
            ChangeRecord changeRecord = row.toJavaObject(ChangeRecord.class);

            if (Subjects.REAL_INCOME.equals(changeRecord.getSubject()) &&
                    changeRecord.getDirection() == 0 &&
                    changeRecord.getCategoryId().equals(IncomeCategoryEnum.COURSE_INCOME.id)) {//课程消耗营收
                Threads.delay(()->{
                    try {
                        handConsumeCourse(changeRecord);
                    } catch (ExecutionException e) {
                        log.error("handConsumeCourse fail",e );
                        throw new RuntimeException(e);
                    }
                } , 3 );
            }
        }
    }

    private void handConsumeCourse(ChangeRecord changeRecord) throws ExecutionException {

        log.info("begin handling 1");

        Map<String, String> tradeProp = loadingCacheOfTradeProp.get(changeRecord.getTradeId()).get();

        if (tradeProp.isEmpty()) {
            return;
        }

        log.info("begin handling 2");

        Long classId = Long.valueOf(tradeProp.get("classId"));
        Long studentId = Long.valueOf(tradeProp.get("studentId"));
        Long regId = Long.valueOf(tradeProp.get("regId"));

        CourseClass courseClass = loadingCacheOfCourseClass.get(classId).get();

        if( ",73,74,75,76,77,78,79,80,".contains(String.valueOf(courseClass.getPeriodId()))){
            return ;
        }

        log.info("begin handling 3");

        Student student = loadingCacheOfStudent.get(studentId).get();
        CourseTemplate courseTemplate = loadingCacheOfCourseTemplate.get(courseClass.getCourseTemplateId()).get();

        if (tradeProp.containsKey("refundClassLectureIds")) {//退费的
            List<Long> classLectureIds = Utils.toLongIds(tradeProp.get("refundClassLectureIds"));
            BigDecimal amount = BigDecimals.calProportion(changeRecord.getAmount(), BigDecimal.ONE, BigDecimal.valueOf(classLectureIds.size()));
            for (Long classLectureId : classLectureIds) {
                ClassLecture classLecture = classLectureService.findById(classLectureId);
                saveConsumeRecord(1,changeRecord, regId, courseClass, student, courseTemplate, amount, classLecture);
            }
        } else if(tradeProp.containsKey("differenceClassLectureIds")){
            saveConsumeRecord(2,changeRecord, regId, courseClass, student, courseTemplate, changeRecord.getAmount(), null );
        } else if(tradeProp.containsKey("classLectureId")){
            log.info("save handling");
            ClassLecture classLecture = classLectureService.findById(Long.valueOf(tradeProp.get("classLectureId")));
            saveConsumeRecord(0 ,changeRecord, regId, courseClass, student, courseTemplate, changeRecord.getAmount(), classLecture);
        }




    }

    private void saveConsumeRecord(int type ,ChangeRecord changeRecord, Long regId, CourseClass courseClass, Student student, CourseTemplate courseTemplate, BigDecimal amount, ClassLecture classLecture) {
        ConsumeRecord consumeRecord = new ConsumeRecord();
        String consumeRecordId = String.valueOf( changeRecord.getChangeRecordId() ) ;
        if(type == 0 || type == 1 ){
            consumeRecordId += "|" + classLecture.getClassLectureId();
        }
        consumeRecord.setConsumeRecordId(consumeRecordId);
        consumeRecord.setType(type);
        consumeRecord.setYear(DateUtils.toCalendar(changeRecord.getCreateTime()).get(Calendar.YEAR));

        consumeRecord.setAreaTeamId(courseClass.getAreaTeamId());
        consumeRecord.setAreaTeamName(courseClass.getAreaTeamName());
        consumeRecord.setBusTeamId(courseClass.getBusTeamId());
        consumeRecord.setBusTeamName(courseClass.getBusTeamName());

        consumeRecord.setCampusId(courseClass.getCampusId());
        consumeRecord.setCampusName(courseClass.getCampusName());

        consumeRecord.setClassId(courseClass.getClassId());
        consumeRecord.setClassName(courseClass.getClassName());
        consumeRecord.setCourseId(courseClass.getCourseTemplateId());
        consumeRecord.setCourseName(courseTemplate.getCourseName());
        consumeRecord.setGradeId(courseClass.getGradeId());
        consumeRecord.setGradeName(courseClass.getGradeName());
        consumeRecord.setSubjectId(courseClass.getSubjectId());
        consumeRecord.setSubjectName(courseClass.getSubjectName());
        consumeRecord.setProductId(courseTemplate.getProductId());
        consumeRecord.setProductName(courseTemplate.getProductName());
        consumeRecord.setSeason(courseClass.getPeriodName());
        consumeRecord.setPeriodId(courseClass.getPeriodId());
        consumeRecord.setPeriodName(courseClass.getPeriodName());

        consumeRecord.setStudentNo(student.getStudentNo());
        consumeRecord.setStudentGradeId(student.getGradeId());
        consumeRecord.setStudentGradeName(student.getGradeName());
        consumeRecord.setStudentId(student.getStudentId());
        consumeRecord.setStudentName(student.getName());

        consumeRecord.setAmount(amount);

        if(classLecture != null ){
            consumeRecord.setClassLectureId(classLecture.getClassLectureId());
            consumeRecord.setClassTime(classLecture.getClassTime());
        }else {
            consumeRecord.setClassLectureId(0l);
            consumeRecord.setClassTime(Calendar.getInstance().getTime());
        }

        consumeRecord.setRegId(regId);
        consumeRecord.setCreateTime(changeRecord.getCreateTime());
        consumeRecord.setUpdateTime(changeRecord.getUpdateTime());

        try {
            consumeRecordService.insertSelective(consumeRecord);
        } catch (Exception e) {
            consumeRecordService.updateSelectiveById(consumeRecord);
        }
    }


}
